package com.authority.controller;


import com.authority.entity.Permission;
import com.authority.entity.User;
import com.authority.entity.UserInfo;
import com.authority.utils.JwtUtils;
import com.authority.utils.MenuTreeUtils;
import com.authority.utils.RedisUtils;
import com.authority.utils.Result;
import com.authority.vo.RouterVo;
import com.authority.vo.TokenVo;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import io.jsonwebtoken.Jwts;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/sysUser")
public class SysUserController extends BaseController {
    @Resource
    JwtUtils jwtUtils;
    @Resource
    RedisUtils redisUtils;

    /**
     * 刷新token
     * @param request
     * @return
     */
    @PostMapping("/refreshToken")
    public Result refreshToken(HttpServletRequest request){
        //从headers中获取token信息
        String token = request.getHeader("token");
        //判断headers中是否存在token
        if(ObjectUtils.isEmpty(token)){
            //从请求参数中获取token
            token=request.getParameter("token");
        }
        //从springSecurity上下文中获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取用户身份信息
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        //定义变量，保存新的token
        String newToken="";
        //验证提交过来的token信息是否是合法的
        if(jwtUtils.validateToken(token,userDetails)){
            //生成新的token
            newToken=jwtUtils.refreshToken(token);
        }
        //获取本次token的过期时间
        long exireTime = Jwts.parser()
                .setSigningKey(jwtUtils.getSecret())
                .parseClaimsJws(newToken.replace("jwt", ""))
                .getBody().getExpiration().getTime();
        //清除原先的token信息
        String oldTokenKey="token_"+token;
        redisUtils.del(oldTokenKey);
        //将新的token信息保存到缓存中
        String newTokenkey="token_"+newToken;
        redisUtils.set(newTokenkey,newToken,jwtUtils.getExpiration());
        //创建tokenVO
        TokenVo tokenVo=new TokenVo(exireTime,newToken);
        //返回数据
        return Result.ok(tokenVo).message("token");

    }

    /**
     * 获取登录的用户信息
     * @return
     */
    @GetMapping("getInfo")
    public Result getUserInfo(){
        //从springSecurity上下文中获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //验证authentication是否存在
        if(authentication==null){
           return Result.error().message("用户查询失败!");
        }
        //获取用户信息
        User user=(User)authentication.getPrincipal();
        //获取该用户拥有的角色权限信息
        List<Permission> permissionList = user.getPermissionList();
        //获取权限编码
        Object[] roles = permissionList.stream().filter(Objects::nonNull).map(Permission::getCode).toArray();
        UserInfo userInfo=new UserInfo(user.getId(),user.getNickName(),user.getAvatar(),null,roles);

        return Result.ok(userInfo).message("用户信息查询成功");
    }

    /**
     *获取用户的菜单数据
     * @return
     */
    @GetMapping("/getMenuList")
    public Result getMenuList(){
        //从springSecurity上下文中获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取用户信息
        User user=(User)authentication.getPrincipal();
        //获取该用户拥有的角色权限信息
        List<Permission> permissionList = user.getPermissionList();
        //筛选当前用户拥有的权限
        List<Permission> collect = permissionList.stream()
                .filter(item -> item != null && item.getType() != 2)    //只筛选目录菜单，过滤掉按钮，0:目录，1:菜单，2:按钮
                .collect(Collectors.toList());
        //生成路由数据
        List<RouterVo> routerVoList = MenuTreeUtils.makeRouter(collect, 0L);
        return Result.ok(routerVoList).message("菜单数据获取成功");

    }

}
